﻿using System;
using System.Windows;
using System.Windows.Media;
using WickedFlame.Core;
using WickedFlame.Core.Layers;
using WickedFlame.Core.Shapes;

namespace WickedFlame.Util.Controls
{
	/// <summary>
	/// Control that displays the complete canvas as a image 
	/// </summary>
    public class CanvasImage :  System.Windows.Controls.Control
	{
		VisualImage visual = null;
		DrawingCanvas _canvas;

        VisualCollection _shapeList;
        /// <summary>
        /// List of shapes that are on the canvas
        /// </summary>
        public VisualCollection ShapeList
        {
            get
            {
                return _shapeList;
            }
            set
            {
                _shapeList = value;
            }
        }

		public CanvasImage()
		{
            _shapeList = new VisualCollection(this);
			this.Loaded += new System.Windows.RoutedEventHandler(OnLoaded);
		}

		void OnLoaded(object sender, System.Windows.RoutedEventArgs e)
		{
			Invalidate();
		}

		public void Invalidate()
		{
			if (DrawingCanvas == null)
				return;

			if (visual == null)
			{
				visual = new VisualImage(DrawingCanvas);
                ShapeList.Add(visual);
			}

			visual.Invalidate();
		}

        /// <summary>
        /// Provide a required override for the GetVisualChild method
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        protected override Visual GetVisualChild(int index)
        {
            if (index < 0 || index > ShapeList.Count)
            {
                throw new ArgumentOutOfRangeException();
            }
            return (Visual)ShapeList[index];
        }

        protected override int VisualChildrenCount
        {
            get
            {
                return ShapeList.Count;
            }
        }

		internal void OnLayerAdded(object sender, LayerAddedEventArgs e)
		{
			Invalidate();
		}

        void CanvasChanged(object sender, EventArgs e)
        {
            this.Invalidate();
        }

		private void Canvas_OnSizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
		{
			this.Width = e.NewSize.Width;
			this.Height = e.NewSize.Height;
		}


        #region Dependencie Proerties

        public DrawingCanvas DrawingCanvas
        {
            get
            {
                return (DrawingCanvas)GetValue(DrawingCanvasProperty);
            }
            set
            {
                SetValue(DrawingCanvasProperty, value);
            }
        }

        public static readonly DependencyProperty DrawingCanvasProperty =
            DependencyProperty.Register("DrawingCanvas", typeof(DrawingCanvas), typeof(CanvasImage), new PropertyMetadata(null));

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            DependencyProperty prop = e.Property;
            if (prop == CanvasImage.DrawingCanvasProperty)
            {
                if (_canvas != null)
                {
                    _canvas.SizeChanged -= new System.Windows.SizeChangedEventHandler(Canvas_OnSizeChanged);
                    _canvas.LayerAdded -= new LayerAddedEventHandler(OnLayerAdded);
                    _canvas.CanvasChanged -= new EventHandler(CanvasChanged);
                }

                DrawingCanvas = e.NewValue as DrawingCanvas;
                _canvas = DrawingCanvas;

                if (_canvas != null)
                {
                    _canvas.SizeChanged += new System.Windows.SizeChangedEventHandler(Canvas_OnSizeChanged);
                    _canvas.LayerAdded += new LayerAddedEventHandler(OnLayerAdded);
                    _canvas.CanvasChanged += new EventHandler(CanvasChanged);
                }
            }
        }

        #endregion

        private class VisualImage : DrawableShape
		{
			DrawingCanvas canvas;

			public VisualImage(DrawingCanvas canvas)
			{
				this.canvas = canvas;
			}

			public override void Draw(DrawingContext drawingContext)
			{
				drawingContext.DrawRectangle(Brushes.White, null, new Rect(0, 0, canvas.Width, canvas.Height));

				using (System.IO.Stream stream = new System.IO.MemoryStream())
				{
					var png = new WickedFlame.Util.Data.PngFileFormat();
					png.Export(canvas, stream);

					var img = new System.Windows.Media.Imaging.BitmapImage();
					img.BeginInit();
					img.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
					img.StreamSource = stream;
					img.EndInit();
					drawingContext.DrawImage(img, new Rect(0, 0, canvas.Width, canvas.Height));
				}
			}
		}
	}
}
